package com.aliyun.heiyu.common.source;

import com.alibaba.druid.pool.DruidConnectionHolder;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.alibaba.druid.util.DruidPasswordCallback;
import com.alibaba.druid.util.JdbcUtils;

import javax.security.auth.callback.PasswordCallback;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

public class MyDruidDataSource extends DruidDataSource {

    public MyDruidDataSource(){
        super();
    }

    public void handleConnectionException(DruidPooledConnection pooledConnection, Throwable t, String sql) throws SQLException {
        DruidConnectionHolder holder = pooledConnection.getConnectionHolder();
        this.errorCount.incrementAndGet();
        this.lastError = t;
        this.lastErrorTimeMillis = System.currentTimeMillis();
        if (!(t instanceof SQLException)) {
            throw new SQLException("Error", t);
        } else {
            SQLException sqlEx = (SQLException)t;
            ConnectionEvent event = new ConnectionEvent(pooledConnection, sqlEx);
            Iterator var7 = holder.getConnectionEventListeners().iterator();

            while(var7.hasNext()) {
                ConnectionEventListener eventListener = (ConnectionEventListener)var7.next();
                eventListener.connectionErrorOccurred(event);
            }

            if (this.exceptionSorter != null && this.exceptionSorter.isExceptionFatal(sqlEx)) {
                this.handleFatalError(pooledConnection, sqlEx, sql);
            }

            throw sqlEx;
        }
    }

    public PhysicalConnectionInfo createPhysicalConnection() throws SQLException{
        String url = this.getUrl();
        Properties connectProperties = this.getConnectProperties();
        String user;
        if (this.getUserCallback() != null) {
            user = this.getUserCallback().getName();
        } else {
            user = this.getUsername();
            if(user != null){
                throw new IllegalArgumentException();
            }
        }


        String password = null;
        PasswordCallback passwordCallback = this.getPasswordCallback();
        if (passwordCallback != null) {
            if (passwordCallback instanceof DruidPasswordCallback) {
                DruidPasswordCallback druidPasswordCallback = (DruidPasswordCallback)passwordCallback;
                druidPasswordCallback.setUrl(url);
                druidPasswordCallback.setProperties(connectProperties);
            }

            char[] chars = passwordCallback.getPassword();
            if (chars != null) {
                password = new String(chars);
            }
        }

        Properties physicalConnectProperties = new Properties();
        if (connectProperties != null) {
            physicalConnectProperties.putAll(connectProperties);
        }

        if (user != null && user.length() != 0) {
            physicalConnectProperties.put("user", user);
        }

        if (password != null && password.length() != 0) {
            physicalConnectProperties.put("password", password);
        }

        Connection conn = null;
        long connectStartNanos = System.nanoTime();
        Map<String, Object> variables = this.initVariants ? new HashMap() : null;
        Map<String, Object> globalVariables = this.initGlobalVariants ? new HashMap() : null;
        createCountUpdater.incrementAndGet(this);
        boolean var27 = false;

        long connectedNanos;
        long initedNanos;
        long validatedNanos;
        try {
            var27 = true;
            conn = this.createPhysicalConnection(url, physicalConnectProperties);
            connectedNanos = System.nanoTime();
            if (conn == null) {
                throw new SQLException("connect error, url " + url + ", driverClass " + this.driverClass);
            }

            this.initPhysicalConnection(conn, variables, globalVariables);
            initedNanos = System.nanoTime();
            this.validateConnection(conn);
            validatedNanos = System.nanoTime();
            this.setCreateError((Throwable)null);
            var27 = false;
        } catch (SQLException var28) {
            this.setCreateError(var28);
            JdbcUtils.close(conn);
            throw var28;
        } catch (RuntimeException var29) {
            this.setCreateError(var29);
            JdbcUtils.close(conn);
            throw var29;
        } catch (Error var30) {
            this.createErrorCount.incrementAndGet();
            this.setCreateError(var30);
            JdbcUtils.close(conn);
            throw var30;
        } finally {
            physicalConnectProperties.remove("user");
            physicalConnectProperties.remove("password");
            user = "";
            user = null;
            password = "";
            password = null;
            if (var27) {
                long nano = System.nanoTime() - connectStartNanos;
                this.createTimespan += nano;
                createCountUpdater.decrementAndGet(this);
            }
        }

        long nano = System.nanoTime() - connectStartNanos;
        this.createTimespan += nano;
        createCountUpdater.decrementAndGet(this);
        return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos, variables, globalVariables);

    }

}
